Northeastern US Shelf Region 2024: Sea Surface Temperature
This report was created to track the sea surface temperature regimes for the Northeastern US continental shelf, an area sampled as part of the NMFS Northeast trawl survey.
DISCLAIMER: Any data within 2-weeks of the current date are subject to revision and may change. Please use caution when reporting information that contains these values.
Northeastern US Shelf Region On a Map
Whenever discussing the Northeastern US Shelf Region in this report, we refer to the following spatial extent displayed below. The coordinates of this bounding box are the same coordinates used to clip the sea surface temperature data.
Annual Warming Trends in the Northeast Shelf
Since the early 1980s, the rate of warming in the Northeast Shelf °F / Decade has been more than triple that of the world’s oceans (0.29°F / Decade Figure 1). The precise causes of the pronounced jump in annual average SSTs in the region from 2009 to 2012 remains an area of active research, but the sustained warm conditions suggest a regime shift in the influence of major ocean currents (i.e., Gulf Stream vs Labrador Current) in the Northeast Shelf. While a long-term increase in SSTs is expected as a result of human-caused climate change, we also expect each year to be influenced by large-scale patterns of natural variability, particularly on sub-global (i.e., regional) scales. SST conditions in the Northeast Shelf for 2023 retain the region’s distinction as being one of the fastest warming ocean regions on the planet; including the 2023 data shows that the Northeast Shelf is warming faster than 97% of the world’s ocean surface.
Figure 1: ?(caption)
2023: SST in the Northeast Shelf
As these broad regional patterns transpired, the Northeast Shelf was experiencing a range of conditions that stood in contrast to recent years and the timing of the North Atlantic’s record temperatures.
What began as one of the warmest years on record for the Northeast Shelf ended on the cooler side, with seasonal conditions not seen in the last decade.
Figure 2: ?(caption)
Air-Sea Interactions: Extratropical Storm Lee
Observed SSTs may both influence and be influenced by atmospheric weather patterns. These interactions can act to amplify warming or cooling of surface waters. Sustained periods of low cloud cover and the consequent direct sunlight can rapidly warm the ocean at the surface. Steady winds can act as a fan, advecting heat away from the ocean and cooling the surface. Strong winds and storm systems may also lower SST through mixing, which can bring cooler water from depth closer to the surface.
During September, extratropical storm Lee traversed the Northeast Shelf, which weakened from hurricane strength as it crossed over Georges Bank on September 16 ?@fig-lee-traversal. The impacts of this storm on the region’s SSTs can be seen in Figure 2 when temperature fell over 5F over a period of 12 days.
Similar storm crossings have occurred in the recent past, including in 2019 when Hurricane Dorian passed through the Northeast Shelf after working its way up the US East Coast. Both years had some of the fewest autumn heatwave days seen in the past two decades (2019: 0 days, 2023: 6 days).
Comparing Annual SST to Historical Conditions
When we compare the annual average SST in the Northeast Shelf for 2023 (55.27°F) to other years, we can see it narrowly beat out 2012 as the second warmest year on record. When we look at the deviation from the long-term average SST (i.e., the annual SST anomaly), the last decade stands out for its exceptional warmth (Figure 3). 2023 extends a pattern that began in 2010 of sustained above-average temperatures. With the exception of 2019 (ranked 13th), every one of the last ten years remains in the top 10 warmest years on record.
Figure 3: ?(caption)
Average Monthly Conditions
Monthly average SSTs (Table 1.) show how variable conditions were throughout the year. For the first third of the year, monthly SSTs were among the top three warmest for those months. May, June, July, & August average SSTs ranked lower, ranging from 4th to 12th warmest. The final four months were each much cooler, ranging from 12th to 19th warmest for those months.
Table 1:
Average monthly sea surface temperatures in the Northeast Shelf
Table 1. Monthly Average Sea Surface Temperatures -
Month
Rank (1982-2023)
Observed Temperature
Climatological Average
Temperature Anomaly
January
4
47.9°F (8.8°C)
45.6°F (7.6°C)
2.3°F (1.3°C)
February
1
46.0°F (7.8°C)
42.8°F (6.0°C)
3.2°F (1.8°C)
March
3
44.4°F (6.9°C)
42.1°F (5.6°C)
2.3°F (1.3°C)
April
2
47.2°F (8.4°C)
44.3°F (6.9°C)
2.9°F (1.6°C)
May
3
51.8°F (11.0°C)
50.1°F (10.0°C)
1.7°F (0.9°C)
June
15
58.6°F (14.8°C)
58.1°F (14.5°C)
0.6°F (0.3°C)
July
2
68.4°F (20.2°C)
65.4°F (18.6°C)
3.0°F (1.6°C)
August
14
68.8°F (20.5°C)
67.8°F (19.9°C)
1.0°F (0.5°C)
September
12
66.0°F (18.9°C)
65.3°F (18.5°C)
0.7°F (0.4°C)
October
19
60.3°F (15.7°C)
60.0°F (15.6°C)
0.3°F (0.1°C)
November
22
54.2°F (12.3°C)
54.3°F (12.4°C)
-0.1°F (-0.0°C)
December
25
48.8°F (9.4°C)
49.7°F (9.8°C)
-0.9°F (-0.5°C)
Data Source: NOAA OISSTv2 Daily Sea Surface Temperature Data.
Climatological Reference Period: 1991-2020.
Daily SSTs in the Northeast Shelf
The annual cycle of SST in the Northeast Shelf exhibits a pattern common to regions in the Northern Hemisphere, with the lowest temperatures observed in March and the highest values observed in August (Figure 4). Daily SST anomalies in 2023 never fell below +-1.97 °F compared to the long-term (1991-2020) average and reached as high as high as 4 °F above the long-term average.
The largest temperature anomalies were observed during November, which also turned out to be the warmest November on record (as highlighted in our Fall 2022 update). Figure 4 also illustrates that, in 2023, 123 days experienced SST anomalies that exceeded the threshold for being considered marine heatwaves, or MHW (more on MHWs below, including Figure 8)
Figure 4: A timeseries of daily SSTs (January 1 through December 31, 2023) with an indication of marine heatwave (MHW) conditions in the Northeast Shelf. Black lines represent the long-term (i.e., 1991 – 2020) average SST, the 10th percentile (i.e., cold spell threshold), and 90th percentile (i.e., heatwave threshold). A solid line indicates the observed SST for each day; red and blue shading illustrates whether each day is considered part of a MHW event.
SST Anomalis & MHW Events
A marine heatwave (MHW) is defined as a period when there are five or more consecutive days when the observed SST is greater than the 90th percentile of the long-term average for that day. Gaps of 2 days or less in this threshold do not constitute a break in the MHW event. Figure 4 illustrates that the Northeast Shelf met the criteria for experiencing a MHW for 123 days in 2023 (or 97% of the year). Superimposing MHW status (black line) over the full timeseries of daily SST anomalies (blue/white/red shading) (Figure 4) reveals that the frequency, duration, and intensity of MHWs has increased in the past decade.
Figure 5: A timeseries of marine heatwave (MHW) conditions in the Northeast Shelf extending from January 1, 2023 through December 31, 2023. The black line represents the long-term (i.e., 1991 – 2020) average SST. The 10th to 90th percentile range is shaded in gray. The heavy line (red for marine heatwave or blue for a non-event) indicates the observed SST this year.
Record Setting Daily Sea Surface Temperatures
Daily SST values in 2023 were some of the highest ever recorded in the Northeast Shelf. Record high SSTs were set for more than half of all days during the months of February, March, & April. February saw the most new records, with 86% of days setting new daily record highs.
Figure 6: ?(caption)
Decline of Below Average SST Temperature Days
As SST in the Northeast Shelf continues to rise, the fraction of days when the region experiences below-average temperatures is expected to continue to fall. In a world without human-caused climate change, we would expect, positive (warm) and negative (cool) SST anomalies to more or less balance out over the span of several years, as various patterns of natural climate variability alternate having a dominant influence on Earth’s climate (e.g., La Niña vs El Niño). What is being observed in the Northeast Shelf (and elsewhere around the world), however, is a loss of that balance: larger fractions of recent years are experiencing above average temperatures and cold spells are becoming vanishingly rare.
During 2023 the Northeast Shelf experienced SSTs below the long-term average for a total of 48 days. A period of less than 2 months, and with no days experiencing temperatures that would qualify as marine cold-spells, the cool-water equivalent of a MHW. These events have become rare, with just 5 days of cold spell conditions in the last 20 years.
Figure 7: ?(caption)
Northeast Shelf SSTs Out of Balance
The complete picture of above and below average conditions for the Northeast Shelf reveals a region out of balance. Since 2010 the Northeast Shelf has experienced a disproportionate number of anomalously hot SSTs and experienced many prolonged MHW events.
Figure 8: ?(caption)
Quarterly SST Trends
Zooming in to sub-annual timescales reveals some interesting patterns: the observed rate of warming in the Northeast Shelf varies throughout the year. Comparisons across the four quarters of the year (Figure 9) reveal that the Northeast Shelf is warming fastest during July-September (~4x the global ocean average)—almost twice the rate seen during January-June (~3x the global ocean average).
Figure 9: ?(caption)
Annual SST Anomaly Map
In addition to the sub-annual (or temporal) variation, there can also be significant spatial variability in annually-averaged SST patterns (Figure 10).
This year the impacts of large-scale variability in major oceanic currents, such as the relative influence of the Gulf Stream versus the Labrador Current was quite apparent. With large pockets of above and below average SST anomalies present along the turbulent path of the Gulf Stream to the South of our study area.
Figure 10: ?(caption)
Quarterly Average SST Maps
Looking at these spatial patterns across the annual quarters of 2023 (Figure 11) shows not only the large spatial variability in SST conditions, but also the significant variation in those patterns over the course of the year.
---title: "Northeastern US Continental Shelf SST Report"author: name: "Adam Kemberling" url: https://github.com/adamkemberling affiliation: Gulf of Maine Research Institutedescription: | Temperature tracking for the Northeastern US Continental Shelf Regiondate: "Updated on: `r Sys.Date()`"format: html: code-fold: true code-tools: true df-print: kable self-contained: trueexecute: echo: false warning: false message: false fig.height: 6 fig.width: 8 fig.align: "center" comment: ""---```{r}# Packages{library(ggpubr)library(lubridate)library(raster)library(here)library(rnaturalearth)library(rgeoboundaries)library(scales)library(sf)library(stars)library(gmRi)library(heatwaveR)library(gt)library(gtExtras)library(patchwork)library(tidyverse)library(ggthemes)library(ggstream)library(ggforce)library(geomtextpath)library(ggHoriPlot)library(sysfonts)library(gtable)}# Support FunctionssuppressPackageStartupMessages(source(here("R/oisst_support_funs.R")))suppressPackageStartupMessages(source(here("R/temp_report_support.R")))# File Pathsmills_path <-cs_path("mills")oisst_path <-cs_path("res", "OISST/oisst_mainstays")# Polygons for mappingnew_england <-ne_states("united states of america", returnclass ="sf")canada <-ne_states("canada", returnclass ="sf")world <-ne_countries(returnclass ="sf")greenland <-ne_states(country ="greenland", returnclass ="sf")# Load bathymetry for the bottom contours:# Bathymetric Contour Databathy <-raster(str_c(cs_path("res","Bathy/"), "ETOPO1/NEShelf_Etopo1_bathy.tiff")) # Make a terra copyfor ggplot using tidyterraelev_terra <- terra::rast(bathy)# Adding Logo to plotlogo_path <-paste0(system.file("stylesheets", package ="gmRi"), "/gmri_logo.png")lab_logo <- magick::image_read(logo_path)``````{r params formatting}# Set the shapefile to use as a parameterparams <-list(region ="inuse_strata")# File paths for various extents based on params$regionregion_paths <-get_timeseries_paths(region_group ="nmfs_trawl_regions", box_location ="cloudstorage")# clean up the nametidy_name <-"Northeastern US Shelf Region"# Current Yearcurrent_yr <-year(Sys.Date())# Use panelsetxaringanExtra::use_panelset()# Turn on the stylesheet:gmRi::use_gmri_style_rmd(css ="gmri_rmarkdown.css")# Turn on the gmri font for plotsshowtext::showtext_auto()``````{r}#| label: style-config#| results: asis# Use GMRI styleuse_gmri_style_rmd()``````{r}#| label: fonts-config#| echo: false# Using Raleway Font because it works# Path to the directory containing the font file (replace with your actual path)font_dir <-paste0(system.file("stylesheets", package ="gmRi"), "/GMRI_fonts/Avenir/")# Register the fontfont_add(family ="Avenir",file.path(font_dir, "LTe50342.ttf"),bold =file.path(font_dir, "LTe50340.ttf"),italic =file.path(font_dir, "LTe50343.ttf"),bolditalic =file.path(font_dir, "LTe50347.ttf"))# Why is the gt package able to add it wtf!!# google_font(name = "Avenir")# Load the fontshowtext::showtext_auto()```# `r paste(tidy_name, current_yr)`: Sea Surface TemperatureThis report was created to track the sea surface temperature regimes for the Northeastern US continental shelf, an area sampled as part of the NMFS Northeast trawl survey.Satellite sea surface temperature data used was obtained from the National Center for Environmental Information (NCEI). With all maps and figures displaying [NOAA's Optimum Interpolation Sea Surface Temperature Data](https://www.ncdc.noaa.gov/oisst).**DISCLAIMER:** Any data within 2-weeks of the current date are subject to revision and may change. Please use caution when reporting information that contains these values.### `r tidy_name` On a MapWhenever discussing the `r tidy_name` in this report, we refer to the following spatial extent displayed below. The coordinates of this bounding box are the same coordinates used to clip the sea surface temperature data.```{r}# Load the bounding box for Northeast Shelftimeseries_path <- region_paths[[params$region]][["timeseries_path"]]poly_path <- region_paths[[params$region]][["shape_path"]]region_extent <-st_read(poly_path, quiet =TRUE)# region_extent <- st_union(region_extent)# Pull extents for the region to set crop extentcrop_x <-st_bbox(region_extent)[c(1,3)]crop_y <-st_bbox(region_extent)[c(2,4)]# Map the study areamap_study_area(region_extent =st_union(region_extent),x_buffer =c(-2, 2),y_buffer =c(-0.75, 0.75), new_england_sf = new_england, canada_sf = canada,greenland_sf = greenland,shape_linetype =2)``````{r}#| label: load-timeseries-data# Set the year of the reportreport_yr <-2023#--------- Northeast Shelf Timeseries --------## Load the timeseriesregion_timeseries <-read_csv( timeseries_path, col_types =cols(), guess_max =1e6)# Clean up the data - add labelsregion_timeseries <- region_timeseries %>%mutate(time =as.Date(time)) %>%distinct(time, .keep_all = T) %>%supplement_season_info() %>%filter(year %in%c(1982:report_yr))# Get heatwave statuses for each day:# Uses area weighted sst by defaultregion_hw <-pull_heatwave_events(temperature_timeseries = region_timeseries, threshold =90, clim_ref_period =c("1991-01-01", "2020-12-31")) %>%supplement_hw_data() %>%filter(doy !=366)# Summarize by year to return mean annual anomalies and varianceannual_summary <- region_hw %>%group_by(year = yr) %>%temperature_summaries_hw() %>%mutate(yr_as_dtime =as.Date(paste0(year, "-07-02")),anom_direction =ifelse(sst_anom >0, "Hot", "Cold"))# Data for the Report Year Onlyreport_yr_only <- region_hw %>%filter(year(time) == report_yr)# Set up the date within a year for Heatmapbase_date <-as.Date("2000-01-01")region_hw <- region_hw %>%mutate(year =year(time),yday =yday(time),flat_date =as.Date(yday-1, origin = base_date),yr_rev =factor(year),yr_rev =fct_rev(yr_rev),hw_thresh_f =as_fahrenheit(mhw_thresh-seas, data_type ="anomalies"),cs_thresh_f =as_fahrenheit(mcs_thresh-seas, data_type ="anomalies"))#--------- Global Oceans Timeseries --------## # Global Temperature Anomaliesglobal_anoms <-read_csv(paste0(oisst_path, "global_timeseries/global_anoms_1982to2011.csv"), guess_max =1e6,col_types =cols()) %>%mutate(year =year(time)) %>%filter(between(year, 1982, report_yr)) %>%supplement_season_info()# summarize by year againglobal_summary <- global_anoms %>%group_by(year) %>%temperature_summaries() %>%mutate(yr_as_dtime =as.Date(paste0(year, "-07-02")),anom_direction =ifelse(area_wtd_anom >0, "Hot", "Cold"))``````{r}#| label: code-all-year-temp-summary# Get the overall average and build labelsall_year_avgs <- annual_summary %>%summarise(avg_temp_c =mean(sst),avg_temp_f =mean(sst_f),avg_anom_c =mean(sst_anom),avg_anom_f =mean(anom_f), .groups ="drop") %>%mutate(temp_label =str_c(round(avg_temp_c, 2), " \u00b0C | ", round(avg_temp_f, 2), " \u00b0F"))# Values I need up front for text# average annual sst, its anomaly value:report_annual_temp <-round(mean(report_yr_only$sst_f, na.rm = T), 2)report_annual_anom <-round(mean(report_yr_only$anom_f, na.rm = T), 2)# What rank this year wasreport_rank <-filter(annual_summary, year == report_yr) %>%pull(sst_rank)global_report_rank <-filter(global_summary, year == report_yr) %>%pull(sst_rank)# Record holder year's temperaturerecord_year_temp <-filter(annual_summary, sst_rank ==1) %>%pull(sst_f)# Note on how the seasons ranked:month_ranks <- region_timeseries %>%supplement_season_info() %>%split(.$month) %>%map_dfr(~ .x %>%group_by(year, month) %>%temperature_summaries()) %>%filter(year == report_yr)# How many days in this year meet mhw criteria# add some acknowledgement of the extreme characteristics:hw_criteria <- report_yr_only %>%pull(mhw_event) %>%sum()```## Annual Warming Trends in the Northeast Shelf```{r}#| label: code-warming-rates#### Run Warming Rate regressions ####rate_data <-list("Northeast Shelf F"=get_decadal_rates(temp_df = annual_summary, temp_col ="area_wtd_f", year_col ="year", year_lim =c(1982, report_yr), area_name ="Northeast Shelf", degree_c = F),"Northeast Shelf C"=get_decadal_rates(temp_df = annual_summary, temp_col ="area_wtd_sst", year_col ="year", year_lim =c(1982, report_yr), area_name ="Northeast Shelf", degree_c = T),"Global All F"=get_decadal_rates(temp_df = global_summary, temp_col ="area_wtd_f", year_col ="year", year_lim =c(1982, report_yr), area_name ="Global Ocean", degree_c = F),"Global All C"=get_decadal_rates(temp_df = global_summary, temp_col ="area_wtd_sst", year_col ="year", year_lim =c(1982, report_yr), area_name ="Global Ocean", degree_c = T))# Build Regression Equation Labelseq_all_f <- rate_data[["Northeast Shelf F"]][["eq_label"]]eq_global_f <- rate_data[["Global All F"]][["eq_label"]]eq_all_c <- rate_data[["Northeast Shelf C"]][["eq_label"]]eq_global_c <- rate_data[["Global All C"]][["eq_label"]]```Since the early 1980s, the rate of warming in the Northeast Shelf `r str_c(rate_data[["GoM All F"]][["decadal_rate"]], "\u00b0F / Decade")` has been more than triple that of the world’s oceans (`r str_c(rate_data[["Global All F"]][["decadal_rate"]], "\u00b0F / Decade")` @fig-global-comparison). The precise causes of the pronounced jump in annual average SSTs in the region from 2009 to 2012 remains an area of active research, but the sustained warm conditions suggest a regime shift in the influence of major ocean currents (i.e., Gulf Stream vs Labrador Current) in the Northeast Shelf. While a long-term increase in SSTs is expected as a result of human-caused climate change, we also expect each year to be influenced by large-scale patterns of natural variability, particularly on sub-global (i.e., regional) scales. SST conditions in the Northeast Shelf for `r report_yr` retain the region’s distinction as being one of the fastest warming ocean regions on the planet; including the `r report_yr` data shows that the Northeast Shelf is warming faster than 97% of the world’s ocean surface.```{r}#| label: fig-global-comparison# Fahrenheit plottemp_simplified <-global_rate_comparison(annual_summary_dat = annual_summary, global_summary_dat = global_summary, eq_all =str_remove(eq_all_c, "1982-2023"), eq_global =str_remove(eq_global_c, "1982-2023"), temp_units ="C",region_label ="Northeast Shelf") +coord_cartesian(clip ="off") +geom_logo(x_npc =0.115, y_npc =-0.175, logo_height =1, height_units ="cm")temp_simplified# # Prevents tiny fonts when saving# showtext::showtext_opts(dpi=300) # # # Save location is local# save_location <- here::here("local_data", "COCA_report_figs/")# # # Gom VS Global - annual trends w/ brackets# ggsave(# plot = temp_simplified, # filename = str_c(save_location, "COCA_NEShelf_sst_rates.jpeg"),# height = unit(2.5, "in"),# width = unit(4, "in"),# dpi = "retina", # bg = "white", # scale = 2)```## 2023: SST in the Northeast ShelfAs these broad regional patterns transpired, the Northeast Shelf was experiencing a range of conditions that stood in contrast to recent years and the timing of the North Atlantic's record temperatures.What began as one of the warmest years on record for the Northeast Shelf ended on the cooler side, with seasonal conditions not seen in the last decade.```{r}#| label: fig-gom-record-temps#----- Plot how unusual this year was:region_hw <- region_hw %>%mutate(is_23 =ifelse(yr ==2023, TRUE, FALSE),yr_col =ifelse(is_23, gmri_cols("orange"), "gray90"),yr_lw =ifelse(is_23, 1.5, 0.8),yr_alpha =ifelse(is_23, 1, 0.5),flat_date =as.Date("2000-01-01") + doy-1)# Flag when temperatures were recordshottest_days <- region_hw %>%group_by(doy) %>%slice_max(order_by = sst_anom, n =1) %>%ungroup() # Get some visual controls for when they are records# Pull some of the hottest yearsgom_23 <-filter(region_hw, yr ==2023) %>%mutate(record_temp_alpha =ifelse(time %in% hottest_days$time, 1, 0.4),record_temp_lw =ifelse(time %in% hottest_days$time, 1.2, 0.7))gom_22 <-filter(region_hw, yr ==2022) %>%mutate(record_temp_alpha =ifelse(time %in% hottest_days$time, 1, 0.4),record_temp_lw =ifelse(time %in% hottest_days$time, 1.2, 0.7))gom_21 <-filter(region_hw, yr ==2021) %>%mutate(record_temp_alpha =ifelse(time %in% hottest_days$time, 1, 0.4),record_temp_lw =ifelse(time %in% hottest_days$time, 1.2, 0.7))n_record_days <- gom_23 %>%filter(record_temp_alpha ==1) %>%distinct(time) %>%nrow()# Make a similar plot for the Northeast Shelfgom_23_record_ts <- gom_23 %>%ggplot(aes(flat_date, anom_f)) +# geom_ribbon(# aes(ymin = cs_thresh_f, ymax = hw_thresh_f), # fill = "lightgray", alpha = 0.4) +geom_texthline(yintercept =0, label ="1991-2020\nClimatological Average", linewidth =1, size =5, family ="Avenir", hjust =0.05) +geom_line(aes(group = yr, linewidth =I(record_temp_lw), alpha =I(record_temp_alpha), color =I(yr_col))) +geom_text(data = gom_23 %>%slice(yday(min(gom_23$time))+65),label ="Record High SSTs", vjust =-5, size =5,fontface ="bold", color =gmri_cols("orange"), family ="Avenir") +scale_x_date(date_breaks ="1 month", labels =date_format("%b"), expand =expansion(add =c(0,0))) +# Tropical Storm Calloutannotate('text',x =as.Date("2000-01-01") +310, # Play around with the coordinates until you're satisfiedy =6.3,label ="Traversal of\nExtratropical Storm\nLee",family ="Avenir") +annotate('curve',x =as.Date("2000-01-01") +310, # Play around with the coordinates until you're satisfiedy =5,yend =2.3,xend =as.Date("2000-01-01") +260,linewidth =0.8,curvature =-0.5,arrow =arrow(length =unit(0.5, 'cm'))) +scale_y_continuous(labels =number_format(suffix = deg_f),expand =expansion(mult =c(0.2, 0.2))) +labs(x ="Day of Year", y ="Sea Surface Temperature Anomaly",title =str_c("Record Warm SST for ", n_record_days, " Days of 2023 in the Northeast Shelf"),subtitle ="(40-45.125N, 65.375-70.875W)") +coord_cartesian(clip ="off") +theme(text =element_text(family ="Avenir")) +geom_logo(x_npc =0.85, y_npc =-.15, logo_height =1, height_units ="cm")gom_23_record_ts```### Air-Sea Interactions: Extratropical Storm LeeObserved SSTs may both influence and be influenced by atmospheric weather patterns. These interactions can act to amplify warming or cooling of surface waters. Sustained periods of low cloud cover and the consequent direct sunlight can rapidly warm the ocean at the surface. Steady winds can act as a fan, advecting heat away from the ocean and cooling the surface. Strong winds and storm systems may also lower SST through mixing, which can bring cooler water from depth closer to the surface.During September, extratropical storm Lee traversed the Northeast Shelf, which weakened from hurricane strength as it crossed over Georges Bank on September 16 @fig-lee-traversal. The impacts of this storm on the region’s SSTs can be seen in @fig-gom-record-temps when temperature fell over 5F over a period of 12 days.Similar storm crossings have occurred in the recent past, including in 2019 when Hurricane Dorian passed through the Northeast Shelf after working its way up the US East Coast. Both years had some of the fewest autumn heatwave days seen in the past two decades (2019: 0 days, 2023: 6 days).## Comparing Annual SST to Historical ConditionsWhen we compare the annual average SST in the Northeast Shelf for `r report_yr` (`r str_c(report_annual_temp, deg_f)`) to other years, we can see it narrowly beat out 2012 as the second warmest year on record. When we look at the deviation from the long-term average SST (i.e., the annual SST anomaly), the last decade stands out for its exceptional warmth (@fig-yr-ranks). `r report_yr` extends a pattern that began in 2010 of sustained above-average temperatures. With the exception of 2019 (ranked 13th), every one of the last ten years remains in the top 10 warmest years on record.```{r}#| label: fig-yr-ranks# Do some data preprank_plot_data <- annual_summary %>%filter(sst_rank <=10) %>%mutate(year_rank =fct_reorder(factor(year), sst_rank, .desc = T),rank =fct_rev(factor(sst_rank)),flag_col =ifelse(year ==2023, gmri_cols("orange"), gmri_cols("blue")),temp_label =str_c(round(sst_f, 2), " \u00b0F | ", round(sst, 2), " \u00b0C"),anom_label =str_c(round(anom_f, 2), " \u00b0F | ", round(sst_anom, 2), " \u00b0C"),label_face =ifelse(year ==2023, "bold", "plain")) # Plot themtemp_rankings_p <- rank_plot_data %>%ggplot() +geom_col(aes(x = anom_f, y = rank, fill =I(flag_col)))+# Year Labelsgeom_text(mapping =aes(x =0, y = rank, label =str_c( year_rank)), # No numbering WINTER Control#label = str_c(rank, ". ", year_rank)), # WINTER Controlfontface ="bold",family ="Avenir",hjust =-.05,color ='white',size =5) +# Temperature Labels - Outside Barsgeom_text(mapping =aes(x = anom_f, y = rank, label = temp_label, group = rank, color =I(flag_col), fontface =I(label_face)),family ="Avenir",hjust =-.05, size =4, show.legend = F) +scale_x_continuous(labels =number_format(suffix =" \u00b0F"), expand =expansion(mult =c(0,0.25))) +labs(x ="Average Annual SST Anomaly",y ="Rank",caption ="",title =str_c("Northeast Shelf Warmest Sea Surface Temperatures")) +theme(plot.background =element_blank(),panel.background =element_blank(),panel.border =element_blank(),axis.line.x =element_blank(),legend.position ="none", plot.margin =margin(t =20, l =10, r =5, b =5)) +coord_cartesian(clip ="off") +geom_logo(x_npc =0.875, y_npc =1.075, logo_height =1, height_units ="cm")temp_rankings_p```### Average Monthly ConditionsMonthly average SSTs (Table 1.) show how variable conditions were throughout the year. For the first third of the year, monthly SSTs were among the top three warmest for those months. May, June, July, & August average SSTs ranked lower, ranging from 4th to 12th warmest. The final four months were each much cooler, ranging from 12th to 19th warmest for those months.```{r}#| label: tbl-monthly-avgs#| tbl-cap-location: bottom#| tbl-cap: "Average monthly sea surface temperatures in the Northeast Shelf"# Would be cool to do a big table here of all months# use formattable or whatever the package is.# want a button style number indicating rank relative to past months# want a sparkline indicating anomaly strength# Indicat e % record temps or % HWmonthly_avgs <- region_hw %>%filter(yr ==2023) %>%group_by(yr, month) %>%summarise(temp_c =mean(sst),clim_c =mean(seas),anom_c =mean(sst_anom),temp_f =as_fahrenheit(temp_c),clim_f =as_fahrenheit(clim_c),anom_f =as_fahrenheit(anom_c, data_type ="anomalies"),anom_list =list(anom_f), # list column for sparkline anomalies.groups ="drop") %>%mutate(across(c(temp_c:anom_f), \(x) signif(x, digits =3))) # Grab info on peak tempspeak_month <- monthly_avgs %>%slice_max(order_by = anom_f, n =1)peak_month_full <- month.name[which(month.abb == peak_month$month)]# Do some benchmarking, where do they all rank by anomaliesmonth_rankings <- region_hw %>%group_by(yr =year(time), month) %>%summarise(mean_anom =mean(sst_anom), .groups ="drop") %>%group_by(month) %>%arrange(desc(mean_anom)) %>%mutate(rank =rank(-mean_anom)) %>%ungroup() %>%arrange(rank, month)# Add rankings backmonthly_avgs <- monthly_avgs %>%left_join(select(month_rankings, -c(mean_anom)),by =join_by(yr, month)) # Create the Monthly Summary Tablemonth_names <-data.frame("month"= month.abb, "month_full"= month.name)month_summ_table <- monthly_avgs %>%left_join(month_names) %>%mutate(across(c(temp_c:anom_f),\(x) sprintf(x, fmt ='%#.1f'))) %>%mutate(temp =md(str_c(temp_f, deg_f, " *(", temp_c, deg_c, ")*")),clim =str_c(clim_f, deg_f, " *(", clim_c, deg_c, ")*"),anom =str_c(anom_f, deg_f, " *(", anom_c, deg_c, ")*"),month =str_c("*", month_full, "*")) %>%select(month, rank, temp, clim, anom) %>%gt(rowname_col ="month") %>%tab_header(title =md(paste0("Table 1. Monthly Average Sea Surface Temperatures - ", params$report_year))) %>%tab_stubhead(label =md("Month")) %>%fmt_markdown(columns =everything(),rows =everything(),md_engine =c("markdown", "commonmark")) %>%cols_label( # Change the column names to the unitsrank =md("Rank (1982-2023)"),temp =md("Observed Temperature"),clim =md("Climatological Average"),anom =md("Temperature Anomaly")) %>%tab_source_note(md("*Data Source: NOAA OISSTv2 Daily Sea Surface Temperature Data.*") ) %>%tab_source_note(md("*Climatological Reference Period: 1991-2020.*")) %>%opt_table_font(font =list(google_font(name ="Raleway")))# # Display Tablemonth_summ_table```## Daily SSTs in the Northeast Shelf```{r}#| label: txt-extreme-events# typical rangeseasonal_cycle_min <-min(report_yr_only$seas_f)seasonal_cycle_max <-max(report_yr_only$seas_f)seasonal_range <-round(seasonal_cycle_max - seasonal_cycle_min, 2)# report_yr rangereport_yr_min <-min(report_yr_only$sst_f)report_yr_min_anom <-round(min(report_yr_only$anom_f), 2)report_yr_min_date <-format(report_yr_only$time[report_yr_only$sst_f == report_yr_min], "%b-%d")report_yr_max <-max(report_yr_only$sst_f)report_yr_max_date <-format(report_yr_only$time[report_yr_only$sst_f == report_yr_max], "%b-%d")report_yr_max_anom <-max(report_yr_only$anom_f)report_yr_max_anom_date <-format(report_yr_only$time[report_yr_only$anom_f == report_yr_max_anom], "%b-%d")report_yr_range <-round(report_yr_max - report_yr_min, 2)report_yr_max <-round(report_yr_max, 2)report_yr_max_anom <-round(report_yr_max_anom, 2)report_yr_min <-round(report_yr_min, 2)```The annual cycle of SST in the Northeast Shelf exhibits a pattern common to regions in the Northern Hemisphere, with the lowest temperatures observed in March and the highest values observed in August (@fig-annual-hw-timeseries). Daily SST anomalies in `r report_yr` never fell below +`r report_yr_min_anom` °F compared to the long-term (1991-2020) average and reached as high as high as `r floor(report_yr_max_anom)` °F above the long-term average.The largest temperature anomalies were observed during November, which also turned out to be the warmest November on record (as highlighted in our [Fall 2022 update](https://www.gmri.org/stories/gulf-of-maine-warming-update-fall-2022/)). @fig-annual-hw-timeseries also illustrates that, in `r report_yr`, `r sum(report_yr_only$mhw_event)` days experienced SST anomalies that exceeded the threshold for being considered marine heatwaves, or MHW (more on MHWs below, including @fig-mhw-heatmap)```{r}#| label: fig-annual-hw-timeseries#| fig.height: 4#| fig-cap: "A timeseries of daily SSTs (January 1 through December 31, 2023) with an indication of marine heatwave (MHW) conditions in the Northeast Shelf. Black lines represent the long-term (i.e., 1991 – 2020) average SST, the 10th percentile (i.e., cold spell threshold), and 90th percentile (i.e., heatwave threshold). A solid line indicates the observed SST for each day; red and blue shading illustrates whether each day is considered part of a MHW event."library(ggpubr)# annual heatwave timeseries# Build a new one from scratch ------------year_hw_dat <- report_yr_onlytemp_units <-"F"# Augment Data year_hw_dat <-mutate( year_hw_dat, cs_thresh_f =as_fahrenheit(mcs_thresh),mhw_event_txt =if_else(mhw_event, "Marine Heatwave", "Non-Heatwave"))# Handling Temperature Units: temp_ops <-switch (EXPR = temp_units,"C"=list(temp_col =expr(sst),anom_col =expr(sst_anom),seas_col =expr(seas),hw_thresh =expr(mhw_thresh),cs_thresh =expr(mcs_thresh),hw_temp =expr(hwe),temp_suff =" \u00b0C"),"F"=list(temp_col =expr(sst_f),anom_col =expr(anom_f),seas_col =expr(seas_f),hw_thresh =expr(mhw_thresh_f),cs_thresh =expr(cs_thresh_f),hw_temp =expr(hwe_f),temp_suff =" \u00b0F"))# Assign to shorter names temp_col <- temp_ops$temp_col anom_col <- temp_ops$anom_col clim_col <- temp_ops$seas_col hw_thresh_col <- temp_ops$hw_thresh cs_thresh_col <- temp_ops$cs_thresh hw_temp_col <- temp_ops$hw_temp# Set colors by name color_vals <-c("Non-Heatwave"="#0571B0", "Marine Heatwave"="darkred")# Flag heatwave Events: hw_events <- year_hw_dat %>%filter(mhw_event == T) %>%group_split(mhw_event_no) %>%map_dfr(function(x){data.frame(id =unique(x$mhw_event_no),llim =min(x$time),rlim =max(x$time),ymax =max(x$sst_f),min_anom =min(x$anom_f),max_anom =max(x$anom_f),mean_anom =mean(x$anom_f),len =nrow(x)) })# Make a df with the label positions to avoid textpathclim_labels_df <- year_hw_dat %>%tail(1) %>%select(time, {{hw_thresh_col}}, {{clim_col}}, {{cs_thresh_col}}) %>%pivot_longer(cols =!"time", values_to ="y", names_to ="labs") %>%mutate(labels =case_when( labs == hw_thresh_col ~"- 90th Percentile", labs == clim_col ~"- 1991-2020 Average", labs == cs_thresh_col ~"- 10th Percentile"),y =case_when( labs == hw_thresh_col ~ y+0.75, labs == clim_col ~ y+0, labs == cs_thresh_col ~ y-0.9),hjust =5+time)# Build the Plothw_temp_p <-ggplot(year_hw_dat) +geom_path(aes(x = time, y = {{temp_col}}, color = mhw_event_txt, group =1), linewidth =0.8, key_glyph ="timeseries") +geom_segment(aes(x = time, xend = time, y = {{clim_col}}, yend = {{temp_col}}, color = mhw_event_txt), alpha =0.25,show.legend = F) +geom_path(aes(x = time, y = {{hw_thresh_col}}),color ="gray10",lty =1,) +geom_path(aes(x = time, y = {{clim_col}}),color ="gray10", lty =1) +geom_path(aes(x = time, y = {{cs_thresh_col}}),color ="gray10", lty =1) +geom_text(data = clim_labels_df,aes(x = hjust, y = y, label = labels), family ="Avenir", hjust =0, size =3.5) +geom_bracket(data = hw_events, aes(xmin = llim, xmax = rlim, y.position = ymax +2, label =str_c(len, " Days")), family ="Avenir") +scale_color_manual(values = color_vals) +scale_x_date(date_labels ="%b", date_breaks ="1 month", expand =expansion(add =c(0,115)),limits =as.Date(str_c(report_yr, c("-01-01", "-12-31"))) +c(0,30)) +scale_y_continuous(labels =number_format(suffix = temp_ops$temp_suff),expand =expansion(mult =c(0.05, .1))) +theme(legend.position ="bottom") +labs(title =str_c("2023: Northeast Shelf SST"),x =NULL, color ="Sea Surface Temperature & Heatwave Status:",fill ="Difference from Average SST",y ="Sea Surface Temperature") +coord_cartesian(clip ="off") +geom_logo(x_npc =0.85, y_npc =1.12, logo_height =1, height_units ="cm")# Show plothw_temp_p```### SST Anomalis & MHW EventsA marine heatwave (MHW) is defined as a period when there are five or more consecutive days when the observed SST is greater than the 90th percentile of the long-term average for that day. Gaps of 2 days or less in this threshold do not constitute a break in the MHW event. @fig-annual-hw-timeseries illustrates that the Northeast Shelf met the criteria for experiencing a MHW for `r hw_criteria` days in `r report_yr` (or 97% of the year). Superimposing MHW status (black line) over the full timeseries of daily SST anomalies (blue/white/red shading) (@fig-annual-hw-timeseries) reveals that the frequency, duration, and intensity of MHWs has increased in the past decade.```{r}#| label: fig-season-mhw-timeline#| fig-height: 5#| eval: true#| fig-cap: "A timeseries of marine heatwave (MHW) conditions in the Northeast Shelf extending from January 1, 2023 through December 31, 2023. The black line represents the long-term (i.e., 1991 – 2020) average SST. The 10th to 90th percentile range is shaded in gray. The heavy line (red for marine heatwave or blue for a non-event) indicates the observed SST this year."# Do this one over again:hw_anom_p <- year_hw_dat %>%mutate(hw_anom_thresh = {{ hw_thresh_col }} - {{ clim_col }},cs_anom_thresh = {{ cs_thresh_col }} - {{ clim_col }}) %>%ggplot() +geom_ribbon(aes(x = time, ymin = cs_anom_thresh, ymax = hw_anom_thresh), fill ="lightgray", alpha =0.4) +geom_path(aes(x = time, y = {{anom_col}}, color = mhw_event_txt, group =1), linewidth =0.8, key_glyph ="timeseries") +geom_textpath(aes(x = time, y =0), color ="gray10", label ="Climatological Avg. +/- \n 10th-90th Percentile Range", hjust = .05, lty =1, family ="Avenir") +geom_bracket(data = hw_events, aes(xmin = llim, xmax = rlim, y.position = max_anom +1, label =str_c(len, " Days")), family ="Avenir", ) +scale_color_manual(values = color_vals) +scale_x_date(date_labels ="%b", #date_labels = "%b %y", date_breaks ="1 month", expand =expansion(add =c(0,0))) +scale_y_continuous(labels =number_format(suffix = temp_ops$temp_suff),expand =expansion(mult =c(0.05, .2))) +theme(legend.position ="bottom", legend.title =element_text(face ="bold")) +labs(title =str_c("2023: Northeast Shelf SST Anomalies"),x =NULL, color ="SST Anomalies & Heatwave Status:",fill ="Difference from Average SST",y ="Sea Surface Temperature Anomaly") +coord_cartesian(clip ="off") +geom_logo(x_npc =0.85, y_npc =1.1, logo_height =1, height_units ="cm")# Show plothw_anom_p```### Record Setting Daily Sea Surface Temperatures```{r}#| label: fig-above-average-days#| fig-cap: "Total days above average daily SST and experience MHW conditions in the Northeast Shelf."#| eval: false# Days beneath the meanhot_summary <- region_hw %>%group_by(yr) %>%mutate(over_avg = sst > seas) %>%summarise(above_avg =sum(over_avg),MHW =sum(mhw_event, na.rm = T)) %>%mutate(`Above Average SST`= above_avg - MHW,col =ifelse(yr ==2023, "black", "transparent")) %>%pivot_longer(c(MHW, `Above Average SST`), values_to ="day_num", names_to ="day_type") # And make a plothot_summary %>%ggplot(aes(yr)) +geom_col(aes(y = day_num, fill = day_type, color =I(col)), position ="stack") +map(list(100, 200, 300), ~geom_hline(yintercept = .x, color ="white", linetype =1)) +scale_fill_manual(values =c("darkred", gmri_cols("orange"))) +scale_x_continuous(expand =expansion(add =c(2, 5))) +theme(legend.position =c(0.15, 0.85)) +labs(x ="Year", y ="Days Above Long-Term Average", title ="Increased Prevalance of Above-Average SST", fill ="")```Daily SST values in `r report_yr` were some of the highest ever recorded in the Northeast Shelf. Record high SSTs were set for more than half of all days during the months of February, March, & April. February saw the most new records, with 86% of days setting new daily record highs.```{r}#| label: fig-percent-record-bars#| fig.height: 4#| eval: true# New hottest daily temps - maybe scratch# Grab the hottest day for each day of the yearhottest_days <- region_hw %>%group_by(doy) %>%slice_max(order_by = sst_anom, n =1) %>%ungroup() # Total Number in report_yrhottest_report_yr <- hottest_days %>%count(yr) %>%filter(yr == report_yr) %>%pull(n)# # Daily Record Temperatureshottest_days <- hottest_days %>%mutate(record_period =case_when( yr == report_yr ~as.character(report_yr), yr < report_yr & yr >2000~"Since 2010", yr <2000~"Before 2000"),flat_date =as.Date(str_c(report_yr, "-01-01")) + (doy -1))# What days set records in report_yrrecords_report_yr <- hottest_days %>%filter(yr == report_yr) %>%#count(month)mutate(record_temp =TRUE) %>%select(yr, time, sst, seas, sst_anom, record_temp)# What percent of days in month were records:record_percents <- region_hw %>%filter(yr == report_yr) %>%full_join(records_report_yr) %>%mutate(record_temp =ifelse(record_temp ==TRUE, TRUE, FALSE)) %>%group_by(yr, month) %>%summarise(n_days =n(),n_records =sum(record_temp, na.rm = T),.groups ="drop") %>%mutate(percent_records = (n_records / n_days),highlight_oct =ifelse(month %in%c("Feb", "Mar", "Apr"), "flag", "filler"))# Build the plotfig_percents <-ggplot(record_percents, aes(month, percent_records, alpha = highlight_oct)) +geom_col() +geom_col(fill =as.character(gmri_cols("orange"))) +geom_text(aes(x = month, y = percent_records, label =str_c(round(percent_records,2)*100, "%")),vjust =-.5, color ='black',fontface ="bold", family ="Avenir") +scale_alpha_manual(values =c("flag"=1, "filler"=0.4)) +scale_y_continuous(labels =percent_format(), limits =c(0,1), expand =expansion(add =c(0,0))) +theme(legend.position ="none") +labs(x ="Month", y ="Fraction of the Month", title =str_c(report_yr, ": Record Warm Daily SST"),subtitle ="Large fractions of Feb-Apr dates set all-time high SST in the Northeast Shelf ") +coord_cartesian(clip ="off") +geom_logo(x_npc =0.875, y_npc =-.15, logo_height =1, height_units ="cm")# Show plotfig_percents```### Decline of Below Average SST Temperature DaysAs SST in the Northeast Shelf continues to rise, the fraction of days when the region experiences below-average temperatures is expected to continue to fall. In a world without human-caused climate change, we would expect, positive (warm) and negative (cool) SST anomalies to more or less balance out over the span of several years, as various patterns of natural climate variability alternate having a dominant influence on Earth’s climate (e.g., La Niña vs El Niño). What is being observed in the Northeast Shelf (and elsewhere around the world), however, is a loss of that balance: larger fractions of recent years are experiencing above average temperatures and cold spells are becoming vanishingly rare.During 2023 the Northeast Shelf experienced SSTs below the long-term average for a total of 48 days. A period of less than 2 months, and with no days experiencing temperatures that would qualify as marine cold-spells, the cool-water equivalent of a MHW. These events have become rare, with just 5 days of cold spell conditions in the last 20 years.```{r}#| label: fig-cold-days#| fig-height: 5#| eval: true# Days beneath the meancold_summary <- region_hw %>%group_by(yr) %>%mutate(under_avg = sst < seas) %>%summarise(below_avg =sum(under_avg),`Cold Spell`=sum(mcs_event, na.rm = T)) %>%mutate(`Below Average SST`= below_avg -`Cold Spell`,col =ifelse(yr ==2023, "black", "transparent")) %>%pivot_longer(c(`Cold Spell`, `Below Average SST`), values_to ="day_num", names_to ="day_type") # And make a plotcold_days_plot <- cold_summary %>%ggplot(aes(yr)) +geom_col(aes(y = day_num, fill = day_type, color =I(col)), position ="stack") +map(list(100, 200, 300), ~geom_hline(yintercept = .x, color ="white", linetype =1)) +scale_fill_manual(values =c(gmri_cols("blue"), "lightblue")) +scale_x_continuous(expand =expansion(add =c(2, 5))) +annotate('curve',x =2022, # Play around with the coordinates until you're satisfiedy =180,yend =68,xend =2023,linewidth =0.5,curvature =-0.15,color ="black",arrow =arrow(length =unit(0.5, 'cm'))) +geom_text(data =filter(cold_summary, yr ==2023) %>%summarise(day_num =sum(day_num)),aes(x =2021.5, y =200, label =str_c(day_num, " Days Below Average")), family ="Avenir", size =3.5) +theme(legend.position =c(0.85, 0.85)) +labs(x ="Year", y ="Days Below Long-Term Average", title ="Falling Number of Below-Average SST Days", fill ="") +coord_cartesian(clip ="off") +geom_logo(x_npc =0.85, y_npc =-.15, logo_height =1, height_units ="cm")cold_days_plot```### Northeast Shelf SSTs Out of BalanceThe complete picture of above and below average conditions for the Northeast Shelf reveals a region out of balance. Since 2010 the Northeast Shelf has experienced a disproportionate number of anomalously hot SSTs and experienced many prolonged MHW events.```{r}#| label: fig-mhw-heatmap#| fig.height: 8# Heatmap: All years:heatmap_p <- region_hw %>%heatwave_heatmap_plot(temp_units ="F", start_yr =1981, end_yr =2023) +labs(title ="Northeast Shelf Heatwave Record",y ="Year",x ="Month") +theme(legend.position ="bottom",legend.title =element_text(angle =0),plot.margin =margin(b =0, t =20)) +guides(fill =guide_colorbar(title ="Sea Surface Temperature Anomaly",title.position ="top", title.hjust =0.5, barwidth =unit(3.5, "in"), barheight =unit(0.5, "cm"), frame.colour ="black", ticks.colour ="black")) +coord_cartesian(clip ="off") +geom_logo(x_npc =0.9, y_npc =1.05, logo_height =1, height_units ="cm")heatmap_p +labs(caption ="")```### Quarterly SST TrendsZooming in to sub-annual timescales reveals some interesting patterns: the observed rate of warming in the Northeast Shelf varies throughout the year. Comparisons across the four quarters of the year (@fig-seasons-comparison) reveal that the Northeast Shelf is warming fastest during July-September (\~4x the global ocean average)—almost twice the rate seen during January-June (\~3x the global ocean average).```{r}#| label: fig-seasons-comparison#| fig.width: 8#| fig.height: 7# Pull the data out by season: annual_summary steps but for each seasonseason_summary <- region_timeseries %>%mutate(month_groups =case_when( month %in%c("Jan", "Feb", "Ma") ~"January - March", month %in%c("Apr", "May", "Jun") ~"April - June", month %in%c("Jul", "Aug", "Sep") ~"July - September", month %in%c("Oct", "Nov", "Dec") ~"October - December")) %>%group_by(yr, month_groups) %>%temperature_summaries()global_season_summary <- global_anoms %>%mutate(month_groups =case_when( month %in%c("Jan", "Feb", "Ma") ~"January - March", month %in%c("Apr", "May", "Jun") ~"April - June", month %in%c("Jul", "Aug", "Sep") ~"July - September", month %in%c("Oct", "Nov", "Dec") ~"October - December")) %>%group_by(yr, month_groups) %>%temperature_summaries() # Think we can Facet, but then the stupid rates won't be there...season_avgs <-bind_rows(list("Northeast Shelf"= season_summary,"Global Ocean"= global_season_summary), .id ="Region") %>%mutate(month_groups =factor(month_groups,levels =c("January - March", "April - June", "July - September", "October - December")))# Decadal Rates Functionrate_calc <-function(.data){ annual_lm <-lm(anom_f ~ yr, data = .data) rate_x <-round(coef(annual_lm)["yr"] *10, 2) eq_lab <-paste0(": ", rate_x, deg_f, " / Decade")mutate(.data, rate_eq = eq_lab)}# Run the numbers to make the labelseason_avgs <- season_avgs %>%group_by(Region, month_groups) %>%group_map( ~rate_calc(.), .keep =TRUE) %>%bind_rows() %>%mutate(rate_eq =str_c(Region, rate_eq))# Make the four panels:season_panels <- season_avgs %>%split(.$month_groups) %>%imap(function(x, y){ season_p <-ggplot(x, aes(yr, anom_f)) +geom_line( data =filter(x, Region =="Northeast Shelf"), color ="gray20", alpha =0.5, linewidth = .5, linetype =3) +geom_point(data =filter(x, Region =="Northeast Shelf"), color ="gray20", size =2, alpha =0.8) +stat_smooth(aes(color = rate_eq), method ="lm", formula = y~x, linetype =1, linewidth =1.5, alpha =0.8,se =FALSE) +facet_wrap(~month_groups, ncol =2) +scale_color_manual(values =c(gmri_cols("gmri green"), gmri_cols("blue"))) +scale_y_continuous(labels =number_format(suffix = deg_f)) +theme(legend.position ="bottom", legend.direction ="vertical",legend.background =element_rect(color ="black", fill ="white")) +guides(color =guide_legend(title.position ="top", title.hjust =0.5)) +labs(x =NULL, y ="SST Anomaly",color =str_c(y, " Trend (1982-2023)"))# Signal that winter isn't over...if(y =="October - December"){ season_p <- season_p +geom_point(data =filter(x, yr ==2023, Region =="Northeast Shelf"), aes(yr, anom_f),shape =21, color ="black", fill ="white", size =1.5)}# Return the plot for that season season_p })# Assemble the plotpanel_plot <- (season_panels$`January - March`|season_panels$`April - June`) / (season_panels$`July - September`| season_panels$`October - December`) +plot_annotation(caption ="") &theme(plot.margin =margin(t =10, b =5, r =2, l =2))panel_plotgrid::grid.raster(lab_logo, x =0.08, y =0, just =c('left', 'bottom'), height =unit(1, "cm"))```## Annual SST Anomaly MapIn addition to the sub-annual (or temporal) variation, there can also be significant spatial variability in annually-averaged SST patterns (@fig-new-england-map).This year the impacts of large-scale variability in major oceanic currents, such as the relative influence of the Gulf Stream versus the Labrador Current was quite apparent. With large pockets of above and below average SST anomalies present along the turbulent path of the Gulf Stream to the South of our study area.```{r}#| label: fig-new-england-map#| fig.height: 6# Set time limits to get dataannual_dates <-as.Date(c(str_c(report_yr,"-01-01"), str_c(report_yr,"-12-31")))# Make data window for the yeardata_window <-data.frame(lon =c(-81, -54.5),lat =c(33.5, 50),time = annual_dates)# Load data, stack and tidyne_anoms <-oisst_window_load(data_window = data_window,anomalies = T,box_location ="cloudstorage", climate_ref ="1991-2020") %>%stack()# Convert to Fne_anoms_f <-calc(ne_anoms, function(x) as_fahrenheit(x, data_type ="anomalies")) %>%setNames(names(ne_anoms))# Process the yearly averagene_annual_anom_f <-mean(ne_anoms_f, na.rm = T)# Color limit for palettestemp_limits <-c(-5, 5)temp_breaks <-c(temp_limits[1], temp_limits[1]/2, 0, temp_limits[2]/2, temp_limits[2])temp_labels <-str_c(c(str_c("< ", temp_limits[1]), temp_limits[1]/2, 0, temp_limits[2]/2, str_c("> ", temp_limits[2])), "\u00b0F")# Make it a stars class to plot with ggplotne_anoms_st <-st_as_stars(ne_annual_anom_f)#### 1. Map the Anomalies in Spaceannual_gom_map <-ggplot() +geom_stars(data = ne_anoms_st) + tidyterra::geom_spatraster_contour(data = elev_terra,breaks =seq(0,-200,-100),alpha =0.75) +geom_sf(data = new_england, fill ="gray90", linewidth = .15) +geom_sf(data = canada, fill ="gray90", linewidth = .15) +geom_sf(data = region_extent,color ="black",linetype =2, linewidth =1,fill ="transparent") +scale_y_continuous(breaks =seq(30, 50, by =2)) +scale_fill_distiller(palette ="RdBu", na.value ="transparent", limit = temp_limits, labels = temp_labels,oob = scales::oob_squish) +coord_sf(xlim =c(-78, -56.5), ylim =c(37.8, 48)) +labs(title =str_c(report_yr, ": Average Temperature Anomalies"),caption ="Anomalies calculated using 1991-2020 climatology.\n100m & 200m contours overlaid to show bathymetric details.") +map_theme(legend.position ="bottom",legend.title =element_text(angle =0, face ="bold", family ="Avenir"))+guides("fill"=guide_colorbar(title ="Average Temperature Anomaly ",title.position ="top",title.hjust =0.5,barwidth =unit(3, "in"),frame.colour ="black",ticks.colour ="black")) # Show figureannual_gom_mapgrid::grid.raster(lab_logo, x =0.1, y =0.05, just =c('left', 'bottom'), height =unit(1, "cm"))```### Quarterly Average SST MapsLooking at these spatial patterns across the annual quarters of `r report_yr` (@fig-four-season-maps) shows not only the large spatial variability in SST conditions, but also the significant variation in those patterns over the course of the year.```{r}#| label: fig-four-season-maps#| fig.width: 8#| fig.height: 6# Four Season Panels# Process the stack into the four 3-month averages# Set time limitsseason_dates <-list("January - March"=distinct(filter(report_yr_only, month %in%c("Jan", "Feb", "Mar")), time) %>%pull(time),"April - June"=distinct(filter(report_yr_only, month %in%c("Apr", "May", "Jun")), time) %>%pull(time),"July - September"=distinct(filter(report_yr_only, month %in%c("Jul", "Aug", "Sep")), time) %>%pull(time),"October - December"=distinct(filter(report_yr_only, month %in%c("Oct", "Nov", "Dec")), time) %>%pull(time))# Grab the dates for each, process the mean season_stacks <-map(season_dates, function(x){ dates_x <-str_c("X", str_replace_all(x, "-", ".")) which_dates <-which(names(ne_anoms_f) %in% dates_x) month_mean <-mean(ne_anoms_f[[which_dates]], na.rm = T)})# Assemble Panels Again:season_panel_maps <-imap(season_stacks, function(x, seasn){ season_df <-data.frame("season"= seasn) ne_season_st <-st_as_stars(x) season_map <-ggplot(data = season_df) +geom_stars(data = ne_season_st) + tidyterra::geom_spatraster_contour(data = elev_terra,breaks =seq(0,-200,-100),alpha =0.75) +geom_sf(data = new_england, fill ="gray90", linewidth = .25) +geom_sf(data = canada, fill ="gray90", linewidth = .25) +geom_sf(data = greenland, fill ="gray90", linewidth = .25) +geom_sf(data = region_extent, color ="black", linetype =2, linewidth =1,fill ="transparent") +scale_y_continuous(breaks =seq(30, 50, by =2)) +scale_fill_distiller(palette ="RdBu", na.value ="transparent", limit = temp_limits, labels = temp_labels,oob = scales::oob_squish) +coord_sf(xlim =c(-78, -56.5), ylim =c(37.8, 48)) +facet_wrap(~season) +map_theme(legend.position ="bottom",legend.title =element_text(angle =0))+guides("fill"=guide_colorbar(title ="Average Temperature Anomaly ",title.position ="top",title.hjust =0.5,barwidth =unit(3, "in"),frame.colour ="black",ticks.colour ="black")) # Show figureseason_map})# Put them together and format themseason_panels_all <- ( season_panel_maps$`January - March`| season_panel_maps$`April - June`) / (season_panel_maps$`July - September`| season_panel_maps$`October - December`) +plot_layout(guides ="collect") &theme(legend.position ='bottom', legend.title =element_text(face ="bold", family ="Avenir"),plot.margin =margin(t =1, b =1, r =2, l =2)) # Display themseason_panels_allgrid::grid.raster(lab_logo, x =0.08, y =0.04, just =c('left', 'bottom'), height =unit(1, "cm"))````r insert_gmri_footer()`